<template>
  <div 
    v-if="visible" 
    :class="[
      'loading-spinner',
      size,
      {
        'fullscreen': fullscreen,
        'with-overlay': showOverlay,
        'delayed': delayedShow
      },
      customClass
    ]"
    :style="containerStyle"
  >
    <!-- 背景遮罩 -->
    <div v-if="showOverlay" class="spinner-overlay"></div>
    
    <!-- 加载动画 -->
    <div class="spinner-container">
      <!-- 不同类型的加载动画 -->
      <div 
        v-if="type === 'spinner'"
        :class="['spinner', `spinner-${color}`]"
        :style="spinnerStyle"
      >
        <div class="spinner-circle"></div>
      </div>
      
      <div 
        v-else-if="type === 'dots'"
        :class="['dots-spinner', `dots-${color}`]"
      >
        <div class="dot"></div>
        <div class="dot"></div>
        <div class="dot"></div>
      </div>
      
      <div 
        v-else-if="type === 'pulse'"
        :class="['pulse-spinner', `pulse-${color}`]"
        :style="pulseStyle"
      ></div>
      
      <div 
        v-else-if="type === 'bars'"
        :class="['bars-spinner', `bars-${color}`]"
      >
        <div class="bar"></div>
        <div class="bar"></div>
        <div class="bar"></div>
        <div class="bar"></div>
      </div>
      
      <!-- 加载文本 -->
      <div v-if="showText && text" class="spinner-text">
        {{ text }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, ref, onMounted, onUnmounted } from 'vue'

const props = defineProps({
  // 基本属性
  visible: {
    type: Boolean,
    default: true
  },
  text: {
    type: String,
    default: '加载中...'
  },
  showText: {
    type: Boolean,
    default: true
  },
  
  // 样式属性
  size: {
    type: String,
    default: 'medium',
    validator: (value) => ['small', 'medium', 'large'].includes(value)
  },
  color: {
    type: String,
    default: 'primary',
    validator: (value) => ['primary', 'secondary', 'success', 'warning', 'error'].includes(value)
  },
  type: {
    type: String,
    default: 'spinner',
    validator: (value) => ['spinner', 'dots', 'pulse', 'bars'].includes(value)
  },
  
  // 布局属性
  fullscreen: {
    type: Boolean,
    default: false
  },
  showOverlay: {
    type: Boolean,
    default: false
  },
  customClass: {
    type: String,
    default: ''
  },
  
  // 延迟显示
  delay: {
    type: Number,
    default: 0
  }
})

const delayedShow = ref(false)
let delayTimer = null

// 计算容器样式
const containerStyle = computed(() => {
  const style = {}
  
  if (props.fullscreen) {
    style.position = 'fixed'
    style.top = '0'
    style.left = '0'
    style.right = '0'
    style.bottom = '0'
    style.zIndex = '9999'
  }
  
  return style
})

// 计算加载器样式
const spinnerStyle = computed(() => {
  const sizeMap = {
    small: '20px',
    medium: '40px',
    large: '60px'
  }
  
  const size = sizeMap[props.size] || sizeMap.medium
  
  return {
    width: size,
    height: size
  }
})

// 计算脉冲样式
const pulseStyle = computed(() => {
  const sizeMap = {
    small: '20px',
    medium: '40px',
    large: '60px'
  }
  
  const size = sizeMap[props.size] || sizeMap.medium
  
  return {
    width: size,
    height: size
  }
})

// 处理延迟显示
const handleDelayedShow = () => {
  if (props.delay > 0) {
    delayTimer = setTimeout(() => {
      delayedShow.value = true
    }, props.delay)
  } else {
    delayedShow.value = true
  }
}

// 清理定时器
const clearDelayTimer = () => {
  if (delayTimer) {
    clearTimeout(delayTimer)
    delayTimer = null
  }
}

onMounted(() => {
  handleDelayedShow()
})

onUnmounted(() => {
  clearDelayTimer()
})
</script>

<style scoped>
.loading-spinner {
  @apply flex items-center justify-center;
}

.loading-spinner.fullscreen {
  @apply fixed inset-0 z-50;
}

.spinner-overlay {
  @apply absolute inset-0 bg-black bg-opacity-50;
}

.spinner-container {
  @apply flex flex-col items-center space-y-3 relative z-10;
}

/* 旋转加载器 */
.spinner {
  @apply relative;
}

.spinner-circle {
  @apply w-full h-full border-4 border-gray-200 border-t-current rounded-full;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* 点状加载器 */
.dots-spinner {
  @apply flex space-x-1;
}

.dots-spinner .dot {
  @apply w-2 h-2 bg-current rounded-full;
  animation: dots 1.4s ease-in-out infinite both;
}

.dots-spinner .dot:nth-child(1) {
  animation-delay: -0.32s;
}

.dots-spinner .dot:nth-child(2) {
  animation-delay: -0.16s;
}

@keyframes dots {
  0%, 80%, 100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}

/* 脉冲加载器 */
.pulse-spinner {
  @apply bg-current rounded-full;
  animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {
  0% {
    transform: scale(0);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 0;
  }
}

/* 条状加载器 */
.bars-spinner {
  @apply flex space-x-1 items-end;
}

.bars-spinner .bar {
  @apply w-1 bg-current;
  height: 20px;
  animation: bars 1.2s ease-in-out infinite;
}

.bars-spinner .bar:nth-child(1) {
  animation-delay: -1.2s;
}

.bars-spinner .bar:nth-child(2) {
  animation-delay: -1.1s;
}

.bars-spinner .bar:nth-child(3) {
  animation-delay: -1.0s;
}

.bars-spinner .bar:nth-child(4) {
  animation-delay: -0.9s;
}

@keyframes bars {
  0%, 40%, 100% {
    transform: scaleY(0.4);
  }
  20% {
    transform: scaleY(1);
  }
}

/* 尺寸样式 */
.loading-spinner.small .spinner-text {
  @apply text-sm;
}

.loading-spinner.medium .spinner-text {
  @apply text-base;
}

.loading-spinner.large .spinner-text {
  @apply text-lg;
}

.loading-spinner.small .dots-spinner .dot {
  @apply w-1 h-1;
}

.loading-spinner.large .dots-spinner .dot {
  @apply w-3 h-3;
}

.loading-spinner.small .bars-spinner .bar {
  height: 15px;
}

.loading-spinner.large .bars-spinner .bar {
  height: 30px;
}

/* 颜色样式 */
.spinner-primary,
.dots-primary,
.pulse-primary,
.bars-primary {
  @apply text-blue-500;
}

.spinner-secondary,
.dots-secondary,
.pulse-secondary,
.bars-secondary {
  @apply text-gray-500;
}

.spinner-success,
.dots-success,
.pulse-success,
.bars-success {
  @apply text-green-500;
}

.spinner-warning,
.dots-warning,
.pulse-warning,
.bars-warning {
  @apply text-yellow-500;
}

.spinner-error,
.dots-error,
.pulse-error,
.bars-error {
  @apply text-red-500;
}

/* 文本样式 */
.spinner-text {
  @apply text-gray-600 font-medium;
}

/* 延迟显示 */
.loading-spinner.delayed {
  @apply opacity-0;
  animation: fadeIn 0.3s ease-in-out forwards;
}

@keyframes fadeIn {
  to {
    opacity: 1;
  }
}
</style>